package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;

import core.JitAdd;
import core.JitCommit;
import core.JitConfig;
import core.JitInit;
import core.JitReset;
import core.JitRm;
import gitobject.Commit;
import repository.Repository;

public class GUI extends JFrame{
	private static final long serialVersionUID = 1L;
	
	private static String repopath;
	static Repository repo;
	static ArrayList<String> repositoryList;
	static Vector<String> unstagedList;
	ArrayList<JLabel> commitList;
	ArrayList<ArrayList<JLabel>> branchList;
	static JTree fileTree;
	
	public GUI() {
		try {
			repo = new Repository(repopath);
		} catch (IOException e) {
			e.printStackTrace();
		}
		GUI.repositoryList = new ArrayList<String>();
		commitList = new ArrayList<JLabel>();
		branchList = new ArrayList<ArrayList<JLabel>>();
	}
	
	public GUI(String path) {
		GUI.repopath = "C:\\Users\\xyz80\\Desktop\\test\\SimpleGit";
		try {
			repo = new Repository(repopath);
		} catch (IOException e) {
			e.printStackTrace();
		}
		GUI.repositoryList = new ArrayList<String>();
		commitList = new ArrayList<JLabel>();
		branchList = new ArrayList<ArrayList<JLabel>>();
	}

	public void initPanel() {
		this.setTitle("Jit GUI");
        this.setSize(400, 300);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setLayout(null);
        
        JPanel panelInit = new JPanel();
        this.setContentPane(panelInit);
        
        JButton btnNew = new JButton("Create a new repository");
        btnNew.setBounds(90, 90, 200, 30);
        
        btnNew.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showPathChooseDialog();
				try {
					JitInit.init(repopath);
					repo = new Repository(repopath);
					GUI.repositoryList.add(repopath);
					mainPanel();
					panelInit.setVisible(false);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
        });
        
        JButton btnOpen = new JButton("Open an exist repository");
        btnOpen.setBounds(90, 150, 200, 30);
        
        btnOpen.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showPathChooseDialog();
				try {
					repo = new Repository(repopath);
					GUI.repositoryList.add(repopath);
					mainPanel();
					panelInit.setVisible(false);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
        });
        
        panelInit.add(btnNew);
        panelInit.add(btnOpen);
	}
	
	private void showPathChooseDialog() {
		JDialog pathChooseDialog = new JDialog(this, "Choose repository path", true);
		pathChooseDialog.setSize(400, 200);
		pathChooseDialog.setResizable(false);
		pathChooseDialog.setLocation(400, 400);
		JPanel panel = new JPanel();
		panel.setLayout(null);
		
		JLabel label1 = new JLabel("Directory:");
		label1.setBounds(20, 30, 70, 30);
		
		JTextField textBox = new JTextField();
		textBox.setBounds(100, 30, 190, 30);
		
		JButton btnSelect = new JButton("Select");
        btnSelect.setBounds(300, 30, 80, 30);
        
        btnSelect.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				fileChooser.showDialog(panel, "Choose");
				if(fileChooser.getSelectedFile() != null) {
					textBox.setText(fileChooser.getSelectedFile().getAbsolutePath());
				}
			}
        });
        
        panel.add(label1);
        panel.add(textBox);
        panel.add(btnSelect);
        
		JButton btnConfirm = new JButton("Confirm");
        btnConfirm.setBounds(80, 120, 100, 30);
        
        btnConfirm.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				GUI.repopath = textBox.getText();
				pathChooseDialog.dispose();
			}
        });
        
        JButton btnExit = new JButton("Exit");
        btnExit.setBounds(200, 120, 100, 30);
        
        btnExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				pathChooseDialog.dispose();
			}
        });
        
        panel.add(btnConfirm);
        panel.add(btnExit);
        
        pathChooseDialog.setContentPane(panel);
        pathChooseDialog.setVisible(true);
	}
	
	private void showOptionDialog() {
		JDialog optionDialog = new JDialog(this, "Option", true);
		optionDialog.setSize(400, 200);
		optionDialog.setResizable(false);
		optionDialog.setLocation(400, 400);
		JPanel panel = new JPanel();
		panel.setLayout(null);
		
		File user = new File(Repository.getGitDir() + File.separator + "config");
		String[] userinfo = new String[2];
		if(user.exists()){
			try {
				FileInputStream is = new FileInputStream(user);
				BufferedReader br = new BufferedReader(new InputStreamReader(is));
				String line = br.readLine();
				while (line != null){
					if(line.contains("name")){
						userinfo[0] = line.split(" ")[2];
					}
					else if(line.contains("email")){
						userinfo[1] = line.split(" ")[2];
					}
					line = br.readLine();
				}
				br.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else {
			user = new File("." + File.separator + "src" + File.separator + ".jitconfig");
			if(user.exists()){
				try {
					FileInputStream is = new FileInputStream(user);
					BufferedReader br = new BufferedReader(new InputStreamReader(is));
					String line = br.readLine();
					while (line != null){
						if(line.contains("name")){
							userinfo[0] = line.split(" ")[2];
						}
						else if(line.contains("email")){
							userinfo[1] = line.split(" ")[2];
						}
						line = br.readLine();
					}
					br.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		JLabel label1 = new JLabel("Name:");
		label1.setBounds(20, 30, 70, 30);
		
		JTextField textBox1 = new JTextField();
		textBox1.setBounds(100, 30, 250, 30);
        
		JLabel label2 = new JLabel("Email:");
		label2.setBounds(20, 70, 70, 30);
		
		JTextField textBox2 = new JTextField();
		textBox2.setBounds(100, 70, 250, 30);
		
		textBox1.setText(userinfo[0]);
		textBox2.setText(userinfo[1]);
		
        panel.add(label1);
        panel.add(textBox1);
        panel.add(label2);
        panel.add(textBox2);
        
        JButton btnConfirm = new JButton("Confirm");
        btnConfirm.setBounds(90, 120, 100, 30);
        
        btnConfirm.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String name = textBox1.getText();
				String email = textBox2.getText();
				try {
					JitConfig.config("--global", "name", name);
					JitConfig.config("--global", "email", email);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				optionDialog.dispose();
			}
        });
        
        panel.add(btnConfirm);
        
        JButton btnExit = new JButton("Exit");
        btnExit.setBounds(200, 120, 100, 30);
        
        btnExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				optionDialog.dispose();
			}
        });
        
        panel.add(btnExit);
        
        optionDialog.setContentPane(panel);
        optionDialog.setVisible(true);
	}
	
	private void showAboutDialog() {
		JDialog aboutDialog = new JDialog(this, "About", true);
		aboutDialog.setSize(400, 200);
		aboutDialog.setResizable(false);
		//aboutDialog.setLocation(400, 400);
		aboutDialog.setLocationRelativeTo(null);
		JPanel panel = new JPanel();
		panel.setLayout(null);
		
		JLabel label1 = new JLabel("<html><body>Jit GUI<br>Version: 0.2.0<body></html>");
		label1.setBounds(20, 10, 300, 64);
		label1.setFont(new Font("Times", Font.BOLD, 20));
		
		JLabel label2 = new JLabel("Teammate:WX/FZY/ZXY");
		label2.setBounds(20, 80, 300, 30);
		
		JLabel label3 = new JLabel("Powered by FZY");
		label3.setBounds(20, 120, 300, 30);
        
        panel.add(label1);
        panel.add(label2);
        panel.add(label3);
        
        JButton btnExit = new JButton("Exit");
        btnExit.setBounds(250, 120, 100, 30);
        
        btnExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				aboutDialog.dispose();
			}
        });
        
        panel.add(btnExit);
        
        aboutDialog.setContentPane(panel);
        aboutDialog.setVisible(true);
	}
	
	private void showCommitDialog() {
		JDialog commitDialog = new JDialog(this, "Commit", true);
		commitDialog.setSize(400, 330);
		commitDialog.setResizable(false);
		commitDialog.setLocationRelativeTo(null);
		JPanel panel = new JPanel();
		panel.setLayout(null);
		
		JLabel label1 = new JLabel("Commit message:");
		label1.setBounds(20, 10, 200, 30);
		
		JTextArea textBox = new JTextArea();
		textBox.setBounds(20, 50, 350, 170);
		textBox.setLineWrap(true);
		textBox.setAutoscrolls(true);
        
        panel.add(label1);
        panel.add(textBox);
        
        JButton btnConfirm = new JButton("Confirm");
        btnConfirm.setBounds(90, 240, 100, 30);
        
        btnConfirm.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String content = textBox.getText();
				try {
					JitCommit.commit(content);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				commitDialog.dispose();
			}
        });
        
        JButton btnExit = new JButton("Exit");
        btnExit.setBounds(200, 240, 100, 30);
        
        btnExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				commitDialog.dispose();
			}
        });
        
        panel.add(btnConfirm);
        panel.add(btnExit);
        
        commitDialog.setContentPane(panel);
        commitDialog.setVisible(true);
	}
	
	public void mainPanel() {
		if(repopath.equals("")) {
			this.setTitle("Jit GUI");
		}
		else {
			this.setTitle("Jit GUI --" + repopath);
		}
        this.setSize(600, 500);
        this.setLocation(40, 40);
        this.setVisible(true);
        
        JPanel panelMain = new JPanel();
        panelMain.setLayout(new BorderLayout());
        
		MenuBar menuBar = new MenuBar(); 
		
		Menu menuRepo = new Menu("Repository");
		menuBar.add(menuRepo);
		MenuItem repo1= new MenuItem("New");
		repo1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				initPanel();
			}
		});
		MenuItem repo2 = new MenuItem("Open");
		repo2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				initPanel();
			}
		});
		MenuItem repo3 = new MenuItem("Option");
		repo3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showOptionDialog();
			}
		});
		menuRepo.add(repo1);
		menuRepo.add(repo2);
		menuRepo.add(repo3);
		
		Menu menuCommit = new Menu("Commit");
		menuBar.add(menuCommit);
		MenuItem commit1 = new MenuItem("Commit");
		commit1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showCommitDialog();
			}
		});
		MenuItem commit2 = new MenuItem("Reset");
		commit2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//JitReset.reset("--mixed", commitId);
				showAboutDialog();
			}
		});
		menuCommit.add(commit1);
		menuCommit.add(commit2);
		
		Menu menuBranch = new Menu("Branch");
		menuBar.add(menuBranch);
		MenuItem branch1 = new MenuItem("Create");
		branch1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showAboutDialog();
			}
		});
		MenuItem branch2 = new MenuItem("Checkout");
		branch2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showAboutDialog();
			}
		});
		MenuItem branch3 = new MenuItem("Delete");
		branch3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showAboutDialog();
			}
		});
		menuBranch.add(branch1);
		menuBranch.add(branch2);
		menuBranch.add(branch3);
		
		Menu menuHelp = new Menu("Help");
		menuBar.add(menuHelp);
		MenuItem help1 = new MenuItem("About");
		help1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showAboutDialog();
			}
		});
		menuHelp.add(help1);
		
	    setMenuBar(menuBar);
	    
	    DefaultMutableTreeNode root = new DefaultMutableTreeNode(repopath);
	    fileTreeBuild(repopath, root);
	    fileTree = new JTree(root);
	    fileTree.setBounds(0, 0, 1000, 1000);

	    //JPanel panelMain = new JPanel();
	    /*JScrollPane panelMain = new JScrollPane();
	    panelMain.add(fileTree);*/
        JScrollPane panelTree = new JScrollPane(fileTree, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        //panelMain.add(fileTree);
        //panelMain.setLayout(null);
        panelMain.add(panelTree, BorderLayout.WEST);
        panelTree.setPreferredSize(new Dimension(300, 600));
	    
        JPanel panelAdd = new JPanel();
        JButton btnRescan = new JButton("Rescan");
        btnRescan.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				fileTreeBuild(repopath, root);
			    fileTree = new JTree(root);
			    panelAdd.getParent().repaint();
			}
		});
        
        JButton btnAdd = new JButton("Add");
        btnAdd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					String path = "";
					//path += fileTree.getSelectionPath().getPath()[0];
					for(int i = 1; i < fileTree.getSelectionPath().getPath().length; i++) {
						path += File.separator + fileTree.getSelectionPath().getPath()[i];
					}
					path = path.split(" ")[0];
					JitAdd.add(path.trim());
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
        
        JButton btnRemove = new JButton("Remove");
        btnRemove.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					String path = "";
					//path += fileTree.getSelectionPath().getPath()[0];
					for(int i = 1; i < fileTree.getSelectionPath().getPath().length; i++) {
						path += File.separator + fileTree.getSelectionPath().getPath()[i];
					}
					path = path.split(" ")[0];
					JitRm.rm(path);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
        
        panelAdd.add(btnRescan);
        panelAdd.add(btnAdd);
        panelAdd.add(btnRemove);
        
        panelAdd.setPreferredSize(new Dimension(100, 40));
        panelMain.add(panelAdd, BorderLayout.SOUTH);
        
        JPanel panelCommit = new JPanel();
        panelCommit.setPreferredSize(new Dimension(1000, 1000));
        panelCommit.setBackground(Color.WHITE);
        panelCommit.setLayout(null);
	    JScrollPane scrollPane = new JScrollPane(panelCommit, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
	    //scrollPane.add(fileTree);
	    //scrollPane.setLayout(null);
	    scrollPane.setPreferredSize(new Dimension(600, 600));
	    //scrollPane.setBackground(Color.RED);
	    panelMain.add(scrollPane, BorderLayout.EAST);
	    
	    int i = 0;
	    generateCommitLink();
	    if(!commitList.isEmpty()) {
	    	System.out.println(1);
		    for(JLabel label: commitList) {
		    	label.setBorder(BorderFactory.createLineBorder(Color.black));
		    	label.setBounds(100 + i * 310, 200, 300, 100);
		    	label.addMouseListener(new MouseListener() {

					@Override
					public void mouseClicked(MouseEvent e) {
						label.setBorder(BorderFactory.createLineBorder(Color.RED));
						
					}

					@Override
					public void mousePressed(MouseEvent e) {}

					@Override
					public void mouseReleased(MouseEvent e) {}

					@Override
					public void mouseEntered(MouseEvent e) {}

					@Override
					public void mouseExited(MouseEvent e) {}
		    		
		    	});
		    	i++;
		    	panelCommit.add(label);
		    }
	    }
	    //scrollPane.revalidate();
	    //panelMain.revalidate();
	    
	    this.add(panelMain);
	    this.repaint();
	    this.revalidate();
	    this.setContentPane(panelMain);
	    this.pack();
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	private static void fileTreeBuild(String path, DefaultMutableTreeNode parent) {
		File dir = new File(path);
		File[] fs = dir.listFiles();
		String fileState = "";
		for(int i = 0; i < fs.length; i++) {
			if(!fs[i].getName().equals(".jit") && !fs[i].getName().equals(".git")) {
				if(fs[i].isFile()) {
					try {
						String newpath = path + File.separator + fs[i].getName();
						newpath = newpath.substring(repopath.length() + 1);
						//System.out.println(newpath);
						fileState = JitAdd.fileState(newpath);
					} catch (Exception e) {
						e.printStackTrace();
					}
					if(fileState.equals("")) {
						parent.add(new DefaultMutableTreeNode(fs[i].getName()));
					}
					else {
						parent.add(new DefaultMutableTreeNode(fs[i].getName() + " (" + fileState + ")"));
					}
				}
				else if(fs[i].isDirectory()) {
					DefaultMutableTreeNode node = new DefaultMutableTreeNode(fs[i].getName());
					parent.add(node);
					fileTreeBuild(path + File.separator + fs[i].getName(), node);
				}
			}
			
		}
    }

	
	public void generateCommitLink() {
		String content = "";
    	
    	File head = new File(Repository.getGitDir() + File.separator + "head");
        if(head.exists()){
			try {
				String text = "";
				FileInputStream in = new FileInputStream(head);
				Long filelen = head.length();
				byte[] filecontent = new byte[filelen.intValue()];
				in.read(filecontent);
				content = new String(filecontent, "UTF-8");
				in.close();
				String path = Repository.getGitDir() + File.separator + content.substring(5).replace("/", File.separator);
				File head2 = new File(path.trim());
				//File head2 = new File("C:\\Users\\xyz80\\Desktop\\test\\SimpleGit\\.jit\\refs\\heads\\master");
				System.out.println(head2.exists());
				if(head2.exists()){
					try {
						in = new FileInputStream(head2);
						filelen = head2.length();
						filecontent = new byte[filelen.intValue()];
						in.read(filecontent);
						content = new String(filecontent, "UTF-8");
						in.close();
						System.out.println(content);
						commitList.clear();
						Commit commit = Commit.deserialize(content);
						text = getCommitInfo(commit);
						commitList.add(new JLabel(text));
						while(!commit.getParent().equals("")) {
							commit = Commit.deserialize(commit.getParent());
							text = getCommitInfo(commit);
							commitList.add(new JLabel(text));
						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		        }			
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
    }
    
    public String getCommitInfo(Commit commit) {
    	String content = "";
    	System.out.println(commit.getAuthor());
    	String[] info = commit.getAuthor().split(" ");
    	String time;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy Z", Locale.ENGLISH);
        Date date = new Date(Long.parseLong(info[2]) * 1000);
        time = simpleDateFormat.format(date);
    	content += "Commit " + commit.getKey().substring(0, 5) + "\n";
    	content += "Author:" + info[0] + " " + info[1] + "\n";
    	content += "Date:" + time + "\n";
		return content;
    }
	
    public static void main(String[] args) {
    	new GUI().initPanel();
    }

}